﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.AspNetCore.Http;

namespace FileStorage.Common
{
    /// <summary>
    ///Amazon S3 上传数据（照片、视频、文档等）
    ///     https://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/csharp_s3_code_examples.html
    /// </summary>
    public class AmazonS3Util
    {
        /// <summary>
        /// 请求客户端
        /// </summary>
#if DEBUG
        private readonly AmazonS3Client _client;
#else
        private readonly IAmazonS3 _client;
#endif

        public AmazonS3Util()
        {
#if DEBUG
            _client = new AmazonS3Client(AmazonS3Config.AccessKeyId, AmazonS3Config.SecretAccessKey, RegionEndpoint.GetBySystemName(AmazonS3Config.RegionName));
#else
            _client = new AmazonS3Client(RegionEndpoint.GetBySystemName(AmazonS3Config.RegionName));
#endif
        }

        /// <summary>
        ///创建一个桶
        /// </summary>
        /// <returns></returns>
        public async Task<bool> PutBucketAsync(string bucketName)
        {
            var request = new PutBucketRequest
            {
                BucketName = bucketName,
                UseClientRegion = true
            };
            var response = await _client.PutBucketAsync(request);
            return response.HttpStatusCode == HttpStatusCode.OK;
        }

        /// <summary>
        /// 查找桶所在的地区
        /// </summary>
        /// <param name="bucketName"></param>
        /// <returns></returns>
        public async Task<string> GetBucketLocationAsync(string bucketName)
        {
            var request = new GetBucketLocationRequest()
            {
                BucketName = bucketName
            };
            var response = await _client.GetBucketLocationAsync(request);
            var bucketLocation = response.Location.ToString();
            return bucketLocation;
        }

        /// <summary>
        /// 上传文件 
        /// </summary>
        /// <param name="file">文件域</param>
        /// <param name="baseDir">根文件夹</param>
        /// <returns></returns>
        public async Task<(bool, string)> PutObjectAsync(IFormFile file, string baseDir = "Common/Test")
        {
            if (file == null) return (false, null);
            var fileName = PathFormatter.Format(file.FileName, "/{yyyy}/{mm}/{dd}/{time}{rand:6}");
            var fileType = file.ContentType switch
            {
                _ when file.ContentType.StartsWith("image") => "images",
                _ when file.ContentType.StartsWith("application/msword") || file.ContentType.StartsWith("application/vnd") || file.ContentType.StartsWith("application/pdf") => "docs",
                _ => "files"
            };
            try
            {
                var key = Path.Join(baseDir, fileType, fileName).Replace("\\", "/");
                var request = new PutObjectRequest
                {
                    BucketName = AmazonS3Config.DefaultBucket,
                    //创建对象时，要指定键名，它在存储桶中唯一地标识该对象
                    Key = key,
                    // 媒体类型
                    ContentType = file.ContentType,
                    // 文件流
                    InputStream = file.OpenReadStream(),
                    //此策略用于对象，它可以从浏览器中读取，无需验证
                    CannedACL = S3CannedACL.PublicRead
                };
                var response = await _client.PutObjectAsync(request);
                // https://hub-system-file.s3.amazonaws.com/Applicant/Apply/timg637087790844301016.jpg
                return response.HttpStatusCode == HttpStatusCode.OK ? (true, $"https://{AmazonS3Config.DefaultBucket}.s3.amazonaws.com/{key}") : (false, null);
            }
            catch (Exception e)
            {
                return (false, e.Message);
            }
        }

        /// <summary>
        /// 删除一个对象
        /// </summary>
        /// <param name="key">删除的对象的键如: Applicant/Apply/timg637087790844301016.jpg</param>
        /// <returns></returns>
        public async Task<bool> DeleteObjectAsync(string key)
        {
            var request = new DeleteObjectRequest
            {
                BucketName = AmazonS3Config.DefaultBucket,
                Key = key
            };
            var response = await _client.DeleteObjectAsync(request);
            return response.HttpStatusCode == HttpStatusCode.OK;
        }

        /// <summary>
        /// 根据特定前缀获取对象列表
        /// </summary>
        /// <param name="prefix">限制对以指定前缀开头的键的响应</param>
        /// <returns></returns>
        public async Task<List<S3Object>> ListObjectsAsync(string prefix = "")
        {
            var list = new ListObjectsRequest
            {
                BucketName = AmazonS3Config.DefaultBucket,
                Prefix = prefix
            };
            var response = await _client.ListObjectsAsync(list);
            return response.S3Objects;
        }

        /// <summary>
        /// 下载一个对象
        /// </summary>
        /// <param name="key">下载的对象的键如: Applicant/Apply/timg637087790844301016.jpg</param>
        /// <returns></returns>
        public async Task<(bool, GetObjectResponse)> GetObjectAsync(string key)
        {
            var request = new GetObjectRequest
            {
                BucketName = AmazonS3Config.DefaultBucket,
                Key = key,
            };

            GetObjectResponse response = await _client.GetObjectAsync(request);
            return (response.HttpStatusCode == HttpStatusCode.OK, response);
        }
    }
}
